package com.fengmi.aop.monitor;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

//切面 = 切入点+通知
@Aspect
@Component
@Slf4j
public class MonitorAspect {

    //定义切入点(通过注解的方式)
    @Pointcut("@annotation(com.fengmi.aop.monitor.MonitorLog)")
    public void point(){

    }




    //通知advice
    @Around("point()")
    public Object serviceMonitor(ProceedingJoinPoint pjp){

        //获取目标类和方法的信息
        String clazzName = pjp.getTarget().getClass().getName();

        String methodName = pjp.getSignature().getName();


        //记录开始时间
        long startTime = System.currentTimeMillis();

        //运行目标(被代理对象)方法
        Object proceed = null;
        try {
            proceed = pjp.proceed();
            //记录结束时间
            long endTime = System.currentTimeMillis();


            Integer seconds = getSeconds(pjp);

            Integer time = (int)(endTime-startTime)/1000;

            if(time >= seconds){

                log.info("====类:{},方法:{},运行时间:{}秒",clazzName,methodName,time);
            }



        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }


        return proceed;

    }


    private Integer getSeconds(JoinPoint joinPoint) throws ClassNotFoundException {
        //获取被代理对象名称
        String targetName = joinPoint.getTarget().getClass().getName();
        //获取目标方法名称
        String methodName = joinPoint.getSignature().getName();
        //获取传入目标方法的参数对象
        Object[] arguments = joinPoint.getArgs();
        //获取class对象
        Class targetClass = Class.forName(targetName);
        //获取对象中的所有方法
        Method[] methods = targetClass.getMethods();
        Integer second = 0;
        //下面是进行匹配，方法名和目标方法名相同，且参数相同，则获取注解内的相应参数，用来进行日志记录
        for (Method method : methods) {
            if (method.getName().equals(methodName)){ //方法的重载
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length){
                    second = method.getAnnotation(MonitorLog.class).time();
                    break;
                }
            }
        }
        return second;
    }




}
